package utils

import (
	"fmt"
	"reflect"
	"sync"
)

var (
	entityUtilsTemp *entityUtils
	entityUtilsOnce sync.Once
)

type entityUtils struct{}

func NewEntityUtils() *entityUtils {
	entityUtilsOnce.Do(func() {
		entityUtilsTemp = &entityUtils{}
	})
	return entityUtilsTemp
}

// CopyFields 不同结构体间相同字段的的复制
func (m *entityUtils) CopyFields(dest any, src any) error {
	srcValue := reflect.ValueOf(src)
	if srcValue.Kind() != reflect.Ptr {
		return fmt.Errorf("source parameter must be a pointer to a struct")
	}

	destValue := reflect.ValueOf(dest)
	if destValue.Kind() != reflect.Ptr {
		return fmt.Errorf("destination parameter must be a pointer to a struct")
	}

	srcElem := srcValue.Elem()
	destElem := destValue.Elem()

	for i := 0; i < srcElem.NumField(); i++ {
		srcField := srcElem.Type().Field(i)
		destField := destElem.FieldByName(srcField.Name)

		if destField.IsValid() && destField.CanSet() {
			destField.Set(srcElem.Field(i))
		}
	}

	return nil
}
